package com.zenithmind.document.pojo.domain;

import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.zenithmind.common.base.BaseEntity;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;

import jakarta.validation.constraints.*;
import java.time.LocalDateTime;

/**
 * 文档分享聚合根
 * 遵循单一职责原则：专注于分享数据的表示和基本操作
 * 遵循开闭原则：通过枚举和方法封装，便于扩展
 *
 * @author ZenithMind Team
 * @since 2025-01-09
 */
@Data
@EqualsAndHashCode(callSuper = true)
@NoArgsConstructor
@TableName("document_share")
@Schema(description = "文档分享聚合根")
public class DocumentShare extends BaseEntity {

    /**
     * 分享类型枚举
     */
    public enum ShareType {
        PUBLIC_LINK(1, "公开链接"),
        PASSWORD_PROTECTED(2, "密码保护"),
        SPECIFIED_USERS(3, "指定用户");

        private final int code;
        private final String description;

        ShareType(int code, String description) {
            this.code = code;
            this.description = description;
        }

        public int getCode() { return code; }
        public String getDescription() { return description; }

        public static ShareType fromCode(int code) {
            for (ShareType type : values()) {
                if (type.code == code) {
                    return type;
                }
            }
            throw new IllegalArgumentException("未知的分享类型代码: " + code);
        }
    }

    /**
     * 分享权限枚举
     */
    public enum SharePermission {
        VIEW_ONLY(1, "仅查看"),
        DOWNLOAD(2, "可下载"),
        EDIT(3, "可编辑");

        private final int code;
        private final String description;

        SharePermission(int code, String description) {
            this.code = code;
            this.description = description;
        }

        public int getCode() { return code; }
        public String getDescription() { return description; }

        public static SharePermission fromCode(int code) {
            for (SharePermission permission : values()) {
                if (permission.code == code) {
                    return permission;
                }
            }
            throw new IllegalArgumentException("未知的分享权限代码: " + code);
        }
    }

    /**
     * 文档ID
     */
    @NotBlank(message = "文档ID不能为空")
    @TableField("document_id")
    @Schema(description = "文档ID")
    private String documentId;

    /**
     * 分享码
     */
    @NotBlank(message = "分享码不能为空")
    @Size(max = 20, message = "分享码长度不能超过20个字符")
    @TableField("share_code")
    @Schema(description = "分享码")
    private String shareCode;

    /**
     * 分享链接
     */
    @TableField("share_url")
    @Schema(description = "分享链接")
    private String shareUrl;

    /**
     * 分享标题
     */
    @Size(max = 200, message = "分享标题长度不能超过200个字符")
    @TableField("title")
    @Schema(description = "分享标题")
    private String title;

    /**
     * 分享描述
     */
    @Size(max = 1000, message = "分享描述长度不能超过1000个字符")
    @TableField("description")
    @Schema(description = "分享描述")
    private String description;

    /**
     * 分享类型
     */
    @NotNull(message = "分享类型不能为空")
    @TableField("share_type")
    @Schema(description = "分享类型")
    private Integer shareType;

    /**
     * 访问密码
     */
    @TableField("access_password")
    @Schema(description = "访问密码")
    private String accessPassword;

    /**
     * 权限设置（1:仅查看, 2:可下载, 3:可编辑）
     */
    @TableField("permission")
    @Schema(description = "权限设置")
    private Integer permission;

    /**
     * 过期时间
     */
    @TableField("expire_time")
    @Schema(description = "过期时间")
    private LocalDateTime expireTime;

    /**
     * 最大访问次数
     */
    @TableField("max_access_count")
    @Schema(description = "最大访问次数")
    private Integer maxAccessCount;

    /**
     * 当前访问次数
     */
    @TableField("access_count")
    @Schema(description = "当前访问次数")
    private Integer accessCount;

    /**
     * 下载次数
     */
    @TableField("download_count")
    @Schema(description = "下载次数")
    private Integer downloadCount;

    /**
     * 状态（0:禁用, 1:启用, 2:已过期）
     */
    @TableField("status")
    @Schema(description = "状态")
    private Integer status;

    /**
     * 分享者ID
     */
    @TableField("sharer_id")
    @Schema(description = "分享者ID")
    private String sharerId;

    /**
     * 最后访问时间
     */
    @TableField("last_access_time")
    @Schema(description = "最后访问时间")
    private LocalDateTime lastAccessTime;

    // ========== 业务方法 ==========

    /**
     * 创建公开分享
     */
    public static DocumentShare createPublic(String documentId, String title, String sharerId) {
        DocumentShare share = new DocumentShare();
        share.setDocumentId(documentId);
        share.setTitle(title);
        share.setSharerId(sharerId);
        share.setShareType(ShareType.PUBLIC_LINK.getCode());
        share.setPermission(SharePermission.VIEW_ONLY.getCode());
        share.generateShareCode();
        share.setAccessCount(0);
        share.setDownloadCount(0);
        share.setStatus(1); // 启用
        return share;
    }

    /**
     * 创建密码保护分享
     */
    public static DocumentShare createPasswordProtected(String documentId, String title,
                                                       String password, String sharerId) {
        DocumentShare share = createPublic(documentId, title, sharerId);
        share.setShareType(ShareType.PASSWORD_PROTECTED.getCode());
        share.setAccessPassword(password);
        return share;
    }

    /**
     * 设置文档ID
     */
    public void setDocumentId(String documentId) {
        if (documentId == null || documentId.trim().isEmpty()) {
            throw new IllegalArgumentException("文档ID不能为空");
        }
        this.documentId = documentId;
    }

    /**
     * 设置分享标题
     */
    public void setTitle(String title) {
        if (title != null && title.length() > 200) {
            throw new IllegalArgumentException("分享标题长度不能超过200个字符");
        }
        this.title = title;
    }

    /**
     * 设置分享者ID
     */
    public void setSharerId(String sharerId) {
        if (sharerId == null || sharerId.trim().isEmpty()) {
            throw new IllegalArgumentException("分享者ID不能为空");
        }
        this.sharerId = sharerId;
    }

    /**
     * 设置分享类型
     */
    public void setShareType(Integer shareType) {
        if (shareType == null) {
            throw new IllegalArgumentException("分享类型不能为空");
        }
        // 验证分享类型是否有效
        ShareType.fromCode(shareType);
        this.shareType = shareType;
    }

    /**
     * 设置分享权限
     */
    public void setPermission(Integer permission) {
        if (permission == null) {
            throw new IllegalArgumentException("分享权限不能为空");
        }
        // 验证权限是否有效
        SharePermission.fromCode(permission);
        this.permission = permission;
    }

    /**
     * 设置访问密码
     */
    public void setAccessPassword(String accessPassword) {
        if (shareType != null && ShareType.PASSWORD_PROTECTED.getCode() == shareType) {
            if (accessPassword == null || accessPassword.trim().isEmpty()) {
                throw new IllegalArgumentException("密码保护分享必须设置访问密码");
            }
            if (accessPassword.length() < 4 || accessPassword.length() > 20) {
                throw new IllegalArgumentException("访问密码长度必须在4-20个字符之间");
            }
        }
        this.accessPassword = accessPassword;
    }

    /**
     * 设置访问次数
     */
    public void setAccessCount(Integer accessCount) {
        this.accessCount = accessCount != null ? accessCount : 0;
    }

    /**
     * 设置下载次数
     */
    public void setDownloadCount(Integer downloadCount) {
        this.downloadCount = downloadCount != null ? downloadCount : 0;
    }

    /**
     * 设置状态
     */
    public void setStatus(Integer status) {
        this.status = status;
    }

    /**
     * 生成分享码
     */
    public void generateShareCode() {
        this.shareCode = java.util.UUID.randomUUID().toString().replace("-", "").substring(0, 8);
    }

    /**
     * 设置分享码
     */
    public void setShareCode(String shareCode) {
        if (shareCode == null || shareCode.trim().isEmpty()) {
            throw new IllegalArgumentException("分享码不能为空");
        }
        if (shareCode.length() > 20) {
            throw new IllegalArgumentException("分享码长度不能超过20个字符");
        }
        this.shareCode = shareCode;
    }

    /**
     * 设置分享链接
     */
    public void setShareUrl(String shareUrl) {
        this.shareUrl = shareUrl;
    }

    /**
     * 设置过期时间
     */
    public void setExpireTime(LocalDateTime expireTime) {
        this.expireTime = expireTime;
    }

    /**
     * 设置最大访问次数
     */
    public void setMaxAccessCount(Integer maxAccessCount) {
        this.maxAccessCount = maxAccessCount;
    }

    /**
     * 获取分享类型枚举
     */
    public ShareType getShareTypeEnum() {
        return shareType != null ? ShareType.fromCode(shareType) : null;
    }

    /**
     * 获取分享权限枚举
     */
    public SharePermission getSharePermissionEnum() {
        return permission != null ? SharePermission.fromCode(permission) : null;
    }

    /**
     * 检查是否已过期
     */
    public boolean isExpired() {
        return expireTime != null && LocalDateTime.now().isAfter(expireTime);
    }

    /**
     * 检查是否达到最大访问次数
     */
    public boolean isAccessLimitReached() {
        return maxAccessCount != null && accessCount != null && accessCount >= maxAccessCount;
    }

    /**
     * 检查是否可以访问
     */
    public boolean canAccess() {
        return status != null && status == 1 && !isExpired() && !isAccessLimitReached();
    }

    /**
     * 检查密码是否正确
     */
    public boolean validatePassword(String inputPassword) {
        if (ShareType.PASSWORD_PROTECTED.getCode() != (shareType != null ? shareType : -1)) {
            return true; // 非密码保护分享不需要验证密码
        }
        return accessPassword != null && accessPassword.equals(inputPassword);
    }

    /**
     * 记录访问
     */
    public void recordAccess() {
        if (accessCount == null) {
            accessCount = 0;
        }
        accessCount++;
        lastAccessTime = LocalDateTime.now();
    }

    /**
     * 记录下载
     */
    public void recordDownload() {
        if (downloadCount == null) {
            downloadCount = 0;
        }
        downloadCount++;
        recordAccess(); // 下载也算访问
    }

    /**
     * 检查是否为热门分享
     */
    public boolean isPopular() {
        return accessCount != null && accessCount >= 100;
    }

    /**
     * 禁用分享
     */
    public void disable() {
        this.status = 0;
    }

    /**
     * 启用分享
     */
    public void enable() {
        this.status = 1;
    }

    /**
     * 标记为已过期
     */
    public void markAsExpired() {
        this.status = 2;
    }
}
